#include "BanManager.h"
#include <fstream>
#include "Utils/Utils.h"
#include "Game/PlayerData.h"
#include "GameSingleton.h"
#include "Subsystems/SubsystemPlayers.h"

namespace PocketSurvival
{
    void BanManager::addBanGuid(const GameGuid &guid)
    {
        m_banGuidSetMutex.lock();
        m_banGuidSet.insert(guid);
        m_banGuidSetMutex.unlock();

        PlayerData *targetPlayer = GameSingleton::singletonPtr->getSingleton<SubsystemPlayers>()->getPlayerDataByGuid(guid);
        if(targetPlayer != nullptr && targetPlayer->client != nullptr)
        {
            targetPlayer->client->disconnect("time out ...");
        }
    }

    bool BanManager::removeBanGuid(const GameGuid &guid)
    {
        std::lock_guard<std::mutex> lk(m_banGuidSetMutex);
        auto it = m_banGuidSet.find(guid);
        if(it != m_banGuidSet.end())
        {
            m_banGuidSet.erase(it);
            return false;
        }
        return false;
    }

    bool BanManager::guidIsInBanSet(const GameGuid &guid)
    {
        std::lock_guard<std::mutex> lk(m_banGuidSetMutex);
        return (m_banGuidSet.find(guid) != m_banGuidSet.end());
    }

    void BanManager::addBanIp(const std::string &ipStr)
    {
        m_banIpSetMutex.lock();
        m_banIpSet.insert(ipStr);
        m_banIpSetMutex.unlock();

        char buff[64];
        std::vector<PlayerData *> playerVec;
        GameSingleton::singletonPtr->getSingleton<SubsystemPlayers>()->getAllPlayerData(playerVec);
        for(PlayerData *playerData : playerVec)
        {
            if(playerData->client != nullptr)
            {
                // std::string sockIpStr = sockaddr_ip((sockaddr_u*)playerData->client->getPeer(), buff, sizeof(buff));
                // if(sockIpStr == ipStr)
                // {
                //     playerData->client->disconnect("time out ...");
                // }
            }
        }
    }
    
    bool BanManager::removeBanIp(const std::string &ipStr)
    {
        std::lock_guard<std::mutex> lk(m_banIpSetMutex);
        auto it = m_banIpSet.find(ipStr);
        if(it != m_banIpSet.end())
        {
            m_banIpSet.erase(it);
            return false;
        }
        return false;
    }

    bool BanManager::ipIsInBanSet(const std::string &ipStr)
    {
        std::lock_guard<std::mutex> lk(m_banIpSetMutex);
        return (m_banIpSet.find(ipStr) != m_banIpSet.end());
    }

    void BanManager::load()
    {
        std::ifstream stream;
        stream.open("./Server/ban.json");
        if(stream.is_open())
        {
            nlohmann::json jsonData;
            stream >> jsonData;

            std::vector<GameGuid> guidVec = jsonData["BanGuid"].get<std::vector<GameGuid>>();
            std::vector<std::string> ipVec = jsonData["BanIp"].get<std::vector<std::string>>();
            for(auto &gameGuid : guidVec)
            {
                m_banGuidSet.insert(gameGuid);
            }
            for(auto &ipStr : ipVec)
            {
                m_banIpSet.insert(ipStr);
            }
        }
        stream.close();
    }

    void BanManager::save()
    {
        nlohmann::json jsonData;
        // 理论上，下面的数据保存是不用加锁的
        jsonData["BanGuid"] = m_banGuidSet;
        jsonData["BanIp"] = m_banIpSet;

        Utils::SaveTextFile("./Server/ban.json", jsonData.dump());
    }


} // namespace PocketSurvival
